package com.ruoyi.settled.helper;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.settled.domain.SettlementAgreement;
import com.ruoyi.settled.service.ISettlementAgreementService;
import com.ruoyi.settled.domain.AgreementRule;
import com.ruoyi.settled.service.IAgreementRuleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class SettlementUtils {

    private static final Logger log = LoggerFactory.getLogger(SettlementUtils.class);

    @Autowired
    private ISettlementAgreementService settlementAgreementService;

    @Autowired
    private IAgreementRuleService agreementRuleService;

    @Value("${python.script.path:cold-chain-settled/src/main/resources/settlement.py}")
    private String pythonScriptPath;

    // 指定临时文件存放目录
    private static final String TEMP_DIR = "cold-chain-settled\\src\\main\\resources\\temp";

    /**
     * 根据合作方编码计算结算金额
     *
     * @param orderAmount 订单金额
     * @param partnerCode 合作方编码
     * @return 结算金额
     */
    public BigDecimal calculateSettlementByPartnerCode(BigDecimal orderAmount, String partnerCode) {
        // 获取结算协议
        SettlementAgreement settlementAgreement = settlementAgreementService.selectSettlementAgreementByPartnerCode(partnerCode);
        if (settlementAgreement == null) {
            throw new IllegalArgumentException("未找到合作方编码为 [" + partnerCode + "] 的结算协议");
        }

        // 获取协议编码
        String agreementCode = settlementAgreement.getAgreementCode();
        if (agreementCode == null || agreementCode.isEmpty()) {
            throw new IllegalArgumentException("合作方编码为 [" + partnerCode + "] 的协议规则为空或不存在");
        }

        // 获取协议规则
        AgreementRule agreementRule = agreementRuleService.selectAgreementRuleByAgreementCode(agreementCode);
        if (agreementRule == null) {
            throw new IllegalArgumentException("协议编码为 [" + agreementCode + "] 的协议规则为空或不存在");
        }

        // 获取结算公式
        String agreementFormula = agreementRule.getAgreementFormula();
        if (agreementFormula == null || agreementFormula.isEmpty()) {
            throw new IllegalArgumentException("协议编码为 [" + agreementCode + "] 的协议结算公式为空");
        }

        // 获取税率
        BigDecimal taxRate = agreementRule.getTaxRate() != null ? agreementRule.getTaxRate() : BigDecimal.ZERO;

        // 构建输入数据
        Map<String, Object> inputData = new HashMap<>();
        inputData.put("formula", agreementFormula);
        inputData.put("order_amount", orderAmount);
        inputData.put("tax_rate", taxRate);
        inputData.put("commission_rate", settlementAgreement.getCommissionRate());
        inputData.put("bonus_amount", settlementAgreement.getBonusRate());

        try {
            // 调用 Python 脚本计算结算金额
            String result = callPythonScript(inputData);
            return new BigDecimal(result);
        } catch (Exception e) {
            log.error("调用Python脚本计算结算金额失败：", e);
            throw new IllegalArgumentException("调用Python脚本计算结算金额失败：" + e.getMessage());
        }
    }

    /**
     * 调用 Python 脚本计算结算金额
     *
     * @param inputData 输入数据
     * @return 结算金额
     * @throws Exception 调用失败时抛出异常
     */
    private String callPythonScript(Map<String, Object> inputData) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();

        // 确保临时目录存在
        Path tempDirPath = Paths.get(TEMP_DIR);
        if (!Files.exists(tempDirPath)) {
            Files.createDirectories(tempDirPath);
            log.debug("创建临时目录: {}", tempDirPath.toAbsolutePath());
        }

        // 创建临时文件
        File tempFile = Files.createTempFile(tempDirPath, "input", ".json").toFile();
        log.debug("临时文件路径: {}", tempFile.getAbsolutePath());

        try {
            // 将输入数据写入临时文件
            objectMapper.writeValue(tempFile, inputData);
            log.debug("JSON input for Python script: {}", objectMapper.writeValueAsString(inputData));

            // 构建 Python 命令
            ProcessBuilder processBuilder = new ProcessBuilder("python", pythonScriptPath, tempFile.getAbsolutePath());
            processBuilder.redirectErrorStream(false); // 不合并标准错误流和标准输出流

            // 启动 Python 进程
            Process process = processBuilder.start();

            // 读取 Python 脚本的输出
            String output = new BufferedReader(new InputStreamReader(process.getInputStream()))
                    .lines().collect(Collectors.joining("\n"));

            // 读取错误输出
            String errorOutput = new BufferedReader(new InputStreamReader(process.getErrorStream()))
                    .lines().collect(Collectors.joining("\n"));

            // 等待 Python 脚本执行完成（超时时间为 30 秒）
            if (!process.waitFor(30, TimeUnit.SECONDS)) {
                process.destroyForcibly();
                throw new RuntimeException("Python脚本执行超时");
            }

            // 检查 Python 脚本的退出码
            int exitCode = process.exitValue();
            if (exitCode != 0) {
                throw new RuntimeException("Python脚本执行失败，退出码：" + exitCode + "\n错误信息：" + errorOutput);
            }

            // 解析 Python 脚本的输出
            Map<String, Object> resultMap = objectMapper.readValue(output, Map.class);
            if (!resultMap.containsKey("settlement_amount")) {
                throw new RuntimeException("Python脚本返回结果格式错误，缺少 settlement_amount 字段");
            }

            return resultMap.get("settlement_amount").toString();
        } finally {
            // 删除临时文件
            if (tempFile.exists() && !tempFile.delete()) {
                log.warn("临时文件删除失败: {}", tempFile.getAbsolutePath());
            }
        }
    }
}